﻿using System;
using System.Collections.Generic;
 
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.StsAdmin;

namespace isl.stsadm.ManageSPEventHandlerExtensions
{
    public class ManageEventHandler : ISPStsadmCommand
    {
        private enum myCommandType
        {
            add,
            remove,
            list
        }

        #region Messages
        const string c_AddHandlerMessage = "Adding Handler {0} To List {1} in Web Site {2}";
        const string c_RemoveHandlerMessage = "Removing Handler {0} From List {1} in Web Site {2}";
        const string c_AddedHandlerMessage = "Added Handler {0} To List {1} in Web Site {2}";
        const string c_RemovedHandlerMessage = "Removed Handler {0} From List {1} in Web Site {2}";
         #endregion
        

        #region input commands
        /*
          
     stsadm 
     -o addeventhandler || removeeventhandler || listeventhandlers 
     
      
     ReceiverClass=SPEChangeItem.SPEChangeItemReceiver 
     ReceiverAssembly=SPEChangeItem 
     Version=1.0.0.0 
     Culture=neutral 
     PublicKeyToken=5957735b8821dba4 
     SiteCollection=http://localhost 
     website=public 
     ListName=ToDoIt 
     
     
     
     */
        #endregion

        #region ISPStsadmCommand Members

        InstallerArgs ia = null;
            

        public string GetHelpMessage(string command)
        {
            command = command.ToLower();
            switch (command)
            {
                case "listeventreceivers":
                    return BuildHelpForEvent(myCommandType.list);
                case "addeventreceiver" :
                    return BuildHelpForEvent(myCommandType.add);
                case "removeeventreceiver":
                    return BuildHelpForEvent(myCommandType.remove);
                default:
                    throw new InvalidOperationException("This command "+ command+ " does not exist");
            }
        }

        public int Run(string command, System.Collections.Specialized.StringDictionary keyValues, out string output)
        {
            ia = new InstallerArgs(keyValues);
            CommandResult cr = CommandResult.Create();
            switch (command)
            {
                case "listeventreceivers":
                    output = "";
                    cr = ListEventHandlers();
                    output = cr.OutputString;
                    
                    break;
                case "addeventreceiver":
                    output = "";
                    cr= AddEventHandler();
                    break;
                case "removeeventreceiver":
                    output = "";
                    cr = RemoveEventHandler();
                    break;
                default:
                    cr.ReturnCode = -2;
                    cr.OutputString = "This command " + command + " does not exist";
                    break;
            }
            output = cr.OutputString;
            return cr.ReturnCode;
        }

        private CommandResult AddEventHandler()
        {
            CommandResult cr = CommandResult.Create();
            try
            {
                Console.WriteLine(ia.SiteCollection);
                using (SPSite site = new SPSite(ia.SiteCollection))
                {
                    Console.WriteLine(ia.WebSite);
                    using (SPWeb web = site.AllWebs[ia.WebSite])
                    {
                        SPList list = web.Lists[ia.ListName];
                        Console.WriteLine(GetAddMessage());

                        DeleteExistingHandler(list );
                        
                        //add new event receiver
                        string asmname = ia.ReceiverAssembly + ",Version=" + ia.Version + ",Culture=" + ia.Culture + ",PublicKeyToken=" + ia.PublicKeyToken;
             
                        list.EventReceivers.Add(ia.AddEventType, asmname, ia.ReceiverClass);

                        Console.WriteLine(GetAddedMessage());
                    }

                }
            }
         
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                cr.ReturnCode = 1;
            }
          
            return cr;
        }

        private CommandResult RemoveEventHandler( )
        {
            CommandResult cr = CommandResult.Create();
            try
            {
                Console.WriteLine(GetDeleteMessage());
                using (SPSite site = new SPSite(ia.SiteCollection))
                {
                    using (SPWeb web = site.AllWebs[ia.WebSite])
                    {
                        SPList list = web.Lists[ia.ListName];
                        DeleteExistingHandler(list );
                    }
                }
                Console.WriteLine(GetDeletedMessage());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                cr.ReturnCode = -1;
            }
            return cr;
        }


        private void DeleteExistingHandler(SPList list )
        {
            for (int i = list.EventReceivers.Count - 1; i > -1; i--)
            {

                if (list.EventReceivers[i].Class == ia.ReceiverClass
                                  && list.EventReceivers[i].Assembly == ia.ReceiverAssembly)
                {
                    list.EventReceivers[i].Delete();
                }

            }
        }

        private CommandResult ListEventHandlers()
        {
            CommandResult cr = CommandResult.Create();
                 
                try
                {
                    cr.OutputString = "Site Collection \"" + ia.SiteCollection + "\"\n";
                    using (SPSite site = new SPSite(ia.SiteCollection))
                    {
                        cr.OutputString += " Web Site \"" + ia.WebSite + "\"\n";
                        using (SPWeb web = site.AllWebs[ia.WebSite])
                        {
                            SPList list = web.Lists[ia.ListName];
                            cr.OutputString += " List Name \"" + ia.ListName + "\"\n";

                            for (int i = list.EventReceivers.Count - 1; i > -1; i--)
                            {
                                SPEventReceiverDefinition sperd = list.EventReceivers[i];

                                cr.OutputString += GetEventHandlerInfoMessage(sperd);

                            }
                        }
                    }
                    cr.ReturnCode = 0;
                }
                catch (Exception ex)
                {
                    cr.OutputString = ex.ToString();
                    cr.ReturnCode = -2;
                }
                           
            
            return cr;
        }


        #endregion

        private string GetEventHandlerInfoMessage(SPEventReceiverDefinition sperd)
        {
            StringBuilder sb = new StringBuilder();
            if (string.IsNullOrEmpty(sperd.Assembly) == false)
            {
            sb.AppendLine("");
            sb.AppendLine("--------");
            if (string.IsNullOrEmpty(sperd.Name) == false)
            {
                sb.AppendLine("Name = " + sperd.Name);
            }
            if (string.IsNullOrEmpty(sperd.Filter) == false)
            {
                sb.AppendLine("Filter = " + sperd.Filter);
            }

            sb.AppendLine("Assembly " + sperd.Assembly);
            sb.AppendLine("Class " + sperd.Class);
            sb.AppendLine("Host Type " + sperd.HostType.ToString());
            sb.AppendLine("--------");
            sb.AppendLine("");
            }

            return sb.ToString();
        }
        
        private string GetAddMessage()
        {
            return string.Format(c_AddHandlerMessage,ia.ReceiverClass,ia.ListName,ia.WebSite);
        }
        private string GetDeleteMessage()
        {
            return string.Format(c_RemoveHandlerMessage,ia.ReceiverClass,ia.ListName,ia.WebSite);
        }
        private string GetAddedMessage()
        {
            return string.Format(c_AddedHandlerMessage,ia.ReceiverClass,ia.ListName,ia.WebSite);
        }
        private string GetDeletedMessage()
        {
            return string.Format(c_RemovedHandlerMessage,ia.ReceiverClass,ia.ListName,ia.WebSite);
        }

        private string BuildHelpForEvent(myCommandType myType)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("Adds event receiver to a specified list");
            sb.AppendLine("");
            sb.AppendLine("-o addeventreceiver");
            sb.AppendLine("");
            sb.AppendLine("sitecollection http://serversitecolname");
            sb.AppendLine("");
            sb.AppendLine("website mywebsitename");
            sb.AppendLine("");
            sb.AppendLine("listname mylistname - the list for which you want to handle events");

            if (myType == myCommandType.add)
            {
                sb.AppendLine("");
                sb.AppendLine("AddEventType itemadding | itemadded | .... - string version of SPEventReceiverType enumeration");
            }

            if (myType == myCommandType.add || myType == myCommandType.remove)
            {
                sb.AppendLine("");
                sb.AppendLine("receiverassembly assembly name of your receiver");
                sb.AppendLine("");
                sb.AppendLine("culture culture of your assembly - look at your assembly manifest to find this");
                sb.AppendLine("");
                sb.AppendLine("publickeytoken your assembly public key token - use sn.exe to find this");
                sb.AppendLine("");
                sb.AppendLine("version your assembly version - e.g 1.0.0.0");
                sb.AppendLine("");
                sb.AppendLine("namespace your receiver class namespace - e.g isl.sharepoint.eventhandlers");
                sb.AppendLine("");
                sb.AppendLine("receiverclass your receiver class name - e.g ISLPreventTaskDelete");
            }
            sb.AppendLine("");
            sb.AppendLine("Note: all of the parameter names are case insensitive but parameter values are case sensitive");

            return sb.ToString();
        }
    }
}
